
using System.Collections.Generic;
using PEMath;
using UnityEngine;

namespace PEPhysx
{
    public class PEPhysxControl : MonoBehaviour
    {
        public Transform player;

        public Transform envTransRoot;

        //逻辑位置
        private PEVector3 LogicPos;

        //逻辑方向
        private PEVector3 LogicDir;

        //逻辑速度
        public int LogicSpeed;

        //倍增
        public float multipler;

        //玩家角色
        private PECylinderCollider playerCollider;

        //碰撞环境
        EnvColliders logicEnv;

        void Start()
        {
            Debug.Log("<color=#FF6A6A>PEPhysx Start</color>");
            InitEnv();
            InitPlayer();
        }

        //模拟游戏场景，实际上是根据帧同步服务器发送的逻辑帧来运行
        private void FixedUpdate()
        {
            UpdateInput();
            if(LogicDir == PEVector3.zero)
                return;
            playerCollider.mPos += LogicDir * LogicSpeed * (PEInt) multipler;
            var borderAdjust = PEVector3.zero;
            playerCollider.CalcCollidersInteraction(logicEnv.GetEnvColliders(), ref LogicDir, ref borderAdjust);

            if(LogicDir != PEVector3.zero)
                LogicPos = playerCollider.mPos + borderAdjust;
            playerCollider.mPos = LogicPos;

            player.position = LogicPos.ConvertViewVector3();
        }

        void UpdateInput()
        {
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");
            LogicDir = new PEVector3(new Vector3(h, 0, v).normalized);
        }

        void InitPlayer()
        {
            var cfg = new ColliderConfig
            {
                mName = "Player",
                mPos = new PEVector3(player.position),
                mType = ColliderType.Cylinder,
                mRadius = (PEInt) player.localScale.x / 2
            };
            playerCollider = new PECylinderCollider(cfg);
            LogicPos = playerCollider.mPos;
            LogicDir = PEVector3.zero;
        }

        void InitEnv()
        {
            logicEnv = new EnvColliders
            {
                colliderConfigs = GenerateConfigs()
            };
            logicEnv.Init();
        }

        List<ColliderConfig> GenerateConfigs()
        {
            BoxCollider[] boxArray = envTransRoot.GetComponentsInChildren<BoxCollider>(false);
            CapsuleCollider[] cylinderArray = envTransRoot.GetComponentsInChildren<CapsuleCollider>(false);
            var envCfgList = new List<ColliderConfig>(boxArray.Length + cylinderArray.Length);
            for (int i = 0; i < boxArray.Length; i++)
            {
                var trans = boxArray[i].transform;
                var cfg = new ColliderConfig
                {
                    mPos = new PEVector3(trans.position),
                    mName = trans.gameObject.name,
                    mType = ColliderType.Box,
                    mSize = new PEVector3(trans.localScale / 2),
                    mAxis = new[] {new PEVector3(trans.right), new PEVector3(trans.up), new PEVector3(trans.forward)}
                };
                envCfgList.Add(cfg);
            }

            for (int i = 0; i < cylinderArray.Length; i++)
            {
                var trans = cylinderArray[i].transform;
                var cfg = new ColliderConfig
                {
                    mPos = new PEVector3(trans.position),
                    mName = trans.gameObject.name,
                    mType = ColliderType.Cylinder,
                    mRadius = (PEInt)(trans.localScale.x/2)
                };
                envCfgList.Add(cfg);
            }

            return envCfgList;
        }
    }
}